/***************************************************************************************
 The copyright in this software is being made available under the BSD License, included
 below. This software may be subject to other third party rights,including patent rights,
 and no such rights are granted under this license.

 Regents of the Tsinghua University, Peking University, Zhejiang University, HKUST
 Tsinghua University, Peking University, Zhejiang University, HKUST 2011

 Copyright (c) 2011, Regents of the Tsinghua University, Peking University, Zhejiang
 University, HKUST. All Rights Reserved.

 Redistribution and use in source and binary forms, with or without modification, are
 permitted provided that the following conditions are met:
   * Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice,
     this list of conditions and the following disclaimer in the documentation
     and/or other materials provided with the distribution.
   * Neither the names of the copyright holders nor the names of its
     contributors may be used to endorse or promote products derived from this
     software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 OF SUCH DAMAGE.
***************************************************************************************/


#ifndef _GLOBAL_H_
#define _GLOBAL_H_

#include <stdio.h>

#include "defines.h"

typedef unsigned char byte;
typedef unsigned int  uint32_t;
typedef unsigned short ushort_t;
#define pel_t byte

typedef enum
{
    I_IMG,
    P_IMG,
    B_IMG,
    MAX_IMG_TYPE
} img_type_t;

typedef enum
{
    SKIP,
    INTER16x16,
    //INTER16x8,
    //INTER8x16,
    INTER8x8,
    INTER4x4,
    I8MB,
    I4MB,
    MAX_MODE_NUM
} mode_type;

typedef enum
{
    STAT_SKIP,
    STAT_INTER16X16,
    STAT_INTER8X8,
    STAT_INTRA8X8,
    STAT_INTER4X4,
    STAT_INTRA4X4,
    MAX_STAT_MODE_NUM
} stat_mode_t;

typedef enum
{
    SUBBLOCK_INTRA8x8,
    SUBBLOCK_INTER8x8,
    SUBBLOCK_INTRA4x4,
    SUBBLOCK_INTER4x4
} sub_mode_t;

typedef enum
{
    FALSE,
    TRUE
} boolean_t;

typedef enum
{
    FRAME_CODING,
    FIELD_CODING,
    PAFF_CODING
} coding_type_t;

typedef enum
{
    SE_HEADER,
    SE_PTYPE,
    SE_MBTYPE,
    SE_REFFRAME,
    SE_MVD,
    SE_INTRAPREDMODE,
    SE_CBP_INTRA,
    SE_LUM_DC_INTRA,
    SE_CHR_DC_INTRA,
    SE_LUM_AC_INTRA,
    SE_CHR_AC_INTRA,
    SE_CBP_INTER,
    SE_LUM_DC_INTER,
    SE_CHR_DC_INTER,
    SE_LUM_AC_INTER,
    SE_CHR_AC_INTER,
    SE_DELTA_QUANT_INTER,
    SE_DELTA_QUANT_INTRA,
    SE_MAX_ELEMENTS
} se_type_t;

typedef enum
{
    BITS_HEADER,
    BITS_TOTAL_MB,
    BITS_MB_MODE,
    BITS_INTER_MB,
    BITS_CBP_MB,
    BITS_COEFF_Y_MB,
    BITS_COEFF_UV_MB,
    BITS_DELTA_QUANT_MB,
    MAX_BITCOUNTER_MB
} bit_count_type_t;

typedef enum
{
    FRAME,
    TOP_FIELD,
    BOTTOM_FIELD
} pic_type_t;

typedef enum
{
    FW,
    BW,
    BI,
    INTRA,
    DIRECTION_NUM
} direction_t;

typedef struct bitstream
{
    byte byte_buf;
    byte stored_byte_buf;
    byte byte_buf_skip;
    byte *stream_buffer;
    int  byte_pos;
    int  bits_to_go;
    int  stored_byte_pos;
    int  stored_bits_to_go;
    int  byte_pos_skip;
    int  bits_to_go_skip;
} bitstream_t;

// Q-coder

typedef struct prob_state
{
    int lps_interval;
    int next_state_lps;
    int next_state_mps;
    int do_switch_mps;
} prob_state_t;

typedef struct prob_context
{
    int mps;
    int state;
    prob_state_t* prob_fsm;
} prob_context_t;



#define NUM_EQ_CX_QCODER           1

#define NUM_CBP_CX_QCODER_INTRA    5
#define NUM_CBP_CX_QCODER_INTER    5

#define NUM_DELTAQP_CX_QCODER      4
#define NUM_INTRAMODE_CX_QCODER    2
#define NUM_INTERREF_CX_QCODER     1

#define NUM_INTERSKIP_CX_QCODER    1
#define NUM_MBTYPE_CX_QCODER       3
#define NUM_MBSUBTYPE_CX_QCODER    2
#define NUM_BLOCKSIZE_CX_QCODER    1
#define NUM_SUBBLOCKSIZE_CX_QCODER 1
#define NUM_PRED_DIRECTION_CX_QCODER 2

#define NUM_MVD_CX_QCODER_MAX      5
#define NUM_MVD_CX_16x16_QCODER    5
#define NUM_MVD_CX_8x8_QCODER      5
#define NUM_MVD_CX_4x4_QCODER      5

#define NUM_EOBFLAG_CX_QCODER      1

//4x4 block
#define NUM_COEFF_B4_CX_QCODER_R_MAX   9
#define NUM_COEFF_B4_CX_QCODER_C_MAX   6
#define NUM_COEFF_B4_CX_QCODER_R_INTRA   9
#define NUM_COEFF_B4_CX_QCODER_C_INTRA   6
#define NUM_COEFF_B4_CX_QCODER_R_INTER   9
#define NUM_COEFF_B4_CX_QCODER_C_INTER   6

//8x8 block
#define NUM_COEFF_B8_CX_QCODER_R_MAX   33
#define NUM_COEFF_B8_CX_QCODER_C_MAX   6
//8x8 block for luma
#define NUM_COEFF_B8_CX_QCODER_R_INTRA   33
#define NUM_COEFF_B8_CX_QCODER_C_INTRA   6
#define NUM_COEFF_B8_CX_QCODER_R_INTER   33
#define NUM_COEFF_B8_CX_QCODER_C_INTER   6
//8x8 block for chroma
#define NUM_COEFF_B8_CX_QCODER_R_INTRA_CHROMA   33
#define NUM_COEFF_B8_CX_QCODER_C_INTRA_CHROMA   6
#define NUM_COEFF_B8_CX_QCODER_R_INTER_CHROMA   33
#define NUM_COEFF_B8_CX_QCODER_C_INTER_CHROMA   6

//16x16 block
#define NUM_COEFF_B16_CX_QCODER_R_MAX  33
#define NUM_COEFF_B16_CX_QCODER_C_MAX  6
#define NUM_COEFF_B16_CX_QCODER_R_INTRA  33
#define NUM_COEFF_B16_CX_QCODER_C_INTRA  6
#define NUM_COEFF_B16_CX_QCODER_R_INTER  33
#define NUM_COEFF_B16_CX_QCODER_C_INTER  6


typedef struct qcoder_env
{
    unsigned long interval;
    unsigned long code;
    int code_bits;
    int pending_byte;
    int is_pending_byte;
    int num_stacked_ffs;
    int num_stacked_zeros;
    int first_byte;
    int nbits; //bit counter, only for rdo and stats [9/22/2011 Will]

    prob_context_t eq_prob_context;

    prob_context_t cx_intra_cbp[NUM_CBP_CX_QCODER_INTRA];
    prob_context_t cx_inter_cbp[NUM_CBP_CX_QCODER_INTER];

    prob_context_t cx_delta_qp[NUM_DELTAQP_CX_QCODER];

    prob_context_t cx_intra_luma_mode[NUM_INTRAMODE_CX_QCODER];
    prob_context_t cx_intra_chroma_mode[NUM_INTRAMODE_CX_QCODER];

    prob_context_t cx_inter_ref;

#define NUM_PARTITION 3 //16x16, 8x8, 4x4
#define NUM_DIRECTION 3 //fw bw bi not intra
    prob_context_t cx_inter_skip[NUM_INTERSKIP_CX_QCODER];
    prob_context_t cx_mbsubtype_Direction[NUM_PARTITION][NUM_DIRECTION];
    prob_context_t cx_mbsubtype[NUM_MBSUBTYPE_CX_QCODER];

    prob_context_t cx_blocksize[NUM_BLOCKSIZE_CX_QCODER];
    prob_context_t cx_subblocksize[NUM_SUBBLOCKSIZE_CX_QCODER];
    prob_context_t cx_pred_direction[NUM_PRED_DIRECTION_CX_QCODER];

    prob_context_t cx_mbtype[NUM_MBTYPE_CX_QCODER];

    prob_context_t cx_mvd_x[NUM_MVD_CX_QCODER_MAX];
    prob_context_t cx_mvd_y[NUM_MVD_CX_QCODER_MAX];

    prob_context_t cx_eob_flag;

    prob_context_t cx_eob_flag_8x8[64];
    prob_context_t cx_eob_flag_4x4[16];
    prob_context_t cx_eob_flag_chroma[64];

    prob_context_t cx_transform_s4_flag;
    prob_context_t cx_transform_s16_flag;

    prob_context_t cx_luma_4x4[NUM_COEFF_B4_CX_QCODER_R_MAX][NUM_COEFF_B4_CX_QCODER_C_MAX];
    prob_context_t cx_luma_8x8[NUM_COEFF_B8_CX_QCODER_R_MAX][NUM_COEFF_B8_CX_QCODER_C_MAX];
    prob_context_t cx_luma_16x16[NUM_COEFF_B16_CX_QCODER_R_MAX][NUM_COEFF_B16_CX_QCODER_C_MAX];
    prob_context_t cx_chroma_8x8[NUM_COEFF_B8_CX_QCODER_R_MAX][NUM_COEFF_B8_CX_QCODER_C_MAX];

} qcoder_env_t;

typedef struct cs_obj
{
    bitstream_t *bitstream;
    int curr_se_nr;
    int bit_counter[MAX_BITCOUNTER_MB];
    qcoder_env_t* qcoder;
} cs_obj_t;

typedef cs_obj_t *cs_ptr_t;

typedef struct bbv_buffer
{
    char  bbv_mode;
    char  vec_flag;
    int   bbs_size;
    int   bitrate;
    int   curr_frm_max_bit;
    int   curr_frm_min_bit;
    int   frm_no;
    int   check_continue;
    int   *frame_bits;
    float frame_rate;
    float bbv_delay;
    float low_delay;
    float frm_out_interval;
} bbv_buffer_t;

typedef struct syntax_element
{
    int type;
    int value1;
    int value2;
    int len;
    int inf;
    int context;
    int k;
    int golomb_grad;
    int golomb_maxlevels;
    uint32_t bitpattern;
#if TRACE
#define             TRACESTRING_SIZE 1000
    char tracestring[TRACESTRING_SIZE];
#endif
    void ( *mapping ) ( int value1, int value2, int *len_ptr, int *info_ptr );
} syntax_element_t;

typedef struct mv_par
{
    short x;
    short y;
    short ref;
} mv_t;

typedef struct bi_mv_par
{
    mv_t fw_mv;
    mv_t bw_mv;
} bi_mv_t;

typedef struct mvd_par
{
    short x;
    short y;
} mvd_t;

typedef struct bi_mvd_par
{
    mvd_t fw_mvd;
    mvd_t bw_mvd;
} bi_mvd_t;


typedef struct best_para
{
    int best_mode;
    uint32_t best_cbp;
    uint32_t best_cbp_16x16;    //  ABT
    uint32_t best_cbp_4x4[4];    //  ABT
    int best_transform_16x16;      //  rong 0110  for ABT
    int best_transform_4x4[4];    //  rong 0110  for ABT
    int best_subblock_type[4];
    int b8_ref[2][2];
    mvd_t    mvd[2][2];
    bi_mvd_t bi_mvd[2][2];
    int b4_ref[4][4];
    mvd_t    mvd_4x4[4][4];
    bi_mvd_t bi_mvd_4x4[4][4];

    //coefficients and run level
    int ****chromacofAC;
    int ****cofAC;
    int **cofAC16x16 ;

    byte recY[16][16];
    byte recUV[2][8][8];
} best_para_t;

typedef struct macroblock
{
    int curr_se_nr;
    int slice_nr;
    int delta_qp;
    int qp;
    int qp_chroma;
    int bit_counter[MAX_BITCOUNTER_MB];
    int mb_type;
    int subblock_type[4];
    int cbp;
    int b8mode[2][2];
    int b16mode;  //  ABT
    int b4mode[2][2][2][2];  //  ABT
    int uvmode;      //u and v use the same mode now
    int y_dc[2][2]; //save the dc level of every b8 block
    int y_16x16_dc;  //  ABT
    int y_4x4_dc[2][2][2][2];
    int uv_dc[2];   // save the dc leve of every uv block
    int y_dc_diff[2][2];
    int y_16x16_dc_diff;
    int y_4x4_dc_diff[2][2][2][2];
    int uv_dc_diff[2];
    int y_dc_pred[2][2];
    int y_16x16_dc_pred;
    int y_4x4_dc_pred[2][2][2][2];
    int uv_dc_pred[2];

    int b8_ref[2][2];
    int b4_ref[4][4]; //[B8][B4]
    mvd_t mvd_4x4[4][4];
    bi_mvd_t bi_mvd_4x4[4][4];

    int ****cofAC;
    int ****chromacofAC;
    int prev_cbp;
    int prev_qp;
    int predict_qp;
    int predict_error;
    mvd_t mvd[2][2];
    bi_mvd_t bi_mvd[2][2];
    struct macroblock *mb_available[3][3];
    int b8_skip[2][2];//is skip or not,for each block of inter8x8
    int transform_16x16;      //  rong 0110  for ABT
    int transform_4x4[4];    //  rong 0110  for ABT
    int cbp_16x16;        //  rong 0110  for ABT
    int cbp_4x4[4];      //  rong 0110  for ABT
} macroblock_t;



typedef struct copyright
{
    int extension_id;
    int copyright_flag;
    int copyright_id;
    int original_or_copy;
    int reserved;
    int copyright_number;
} copyright_t;

typedef struct camera_para
{
    int reserved;
    int camera_id;
    int height_of_image_device;
    int focal_length;
    int f_number;
    int vertical_angle_of_view;
    int camera_position_x;
    int camera_position_y;
    int camera_position_z;
    int camera_direction_x;
    int camera_direction_y;
    int camera_direction_z;
    int image_plane_vertical_x;
    int image_plane_vertical_y;
    int image_plane_vertical_z;
} camera_para_t;

typedef struct snr_par
{
    float snr_y;
    float snr_u;
    float snr_v;
    float snr_y1;
    float snr_u1;
    float snr_v1;
    float snr_ya;
    float snr_ua;
    float snr_va;
} snr_t;

typedef struct input_par
{
    char in_file[100];
    char out_file[100];
    char recon_file[100];
    char trace_file[100];
    char bbv_mode;
    int  no_frames;
    int  qp_first;
    int  qp_p;
    int  qp_b;
    int  jumpd;
    int  search_range;
    int  ref_num;
    int  img_width;
    int  img_height;
    int  yuv_format;
    int  color_depth;
    int  intra_upd;
    int  blk_size[MAX_MODE_NUM][2];
    int  infile_header;
#ifdef OPT_HP
	int  hp_coding;
#endif
    int  intra_period;
    int  succe_b;
    int  inter_search_16x16;
    //int  inter_search_16x8;
    //int  inter_search_8x16;
    int  inter_search_8x8;
    int  rdopt;
    int  aspect_ratio_infor;
    int  frame_rate_code;
    int  bit_rate_lower;
    int  bit_rate_upper;
    int  slice_weight_flag;
    int  mb_weight_flag;
    int  vec_period;
    int  seqheader_period;
    int  bbv_buf_size;
    int  bbs_size;
    int  video_format;
    int  color_description;
    int  color_primaries;
    int  matrix_coeff;
    int  hour;
    int  minute;
    int  second;
    int  frame_offset;
    int  profile_id;
    int  level_id;
    int  progressive_sequence;
    int  low_delay;
    int  chroma_format;
    int  sample_precision;
    int  video_range;
    int  frame_pred_frame_dct;
    //int  progressive_frame;
    int  fixed_pic_qp;
    int  time_code_flag;
    int  display_horizontal_size;
    int  display_vertical_size;
    int  dct_adaptive_flag;
    int  slice_mode;
    int  slice_row_nr;
    int  skip_mode_flag;
    int  rc_enable;
    int  bit_rate;
    int  init_qp;
    int  basic_unit;
    int  channel_type;
    int  frame_rate;
    int  bi_me, bi_me_refine, bi_me_range, bi_sub_me;
    int  ABTen, IABTen, InterABTen;
    int  max_num_references;
    int AdaptiveRounding;
    int AdaptRndWeight[6];

#ifdef RDO_Q
    int UseRDO_Q8 ;
    int UseRDO_Q16 ;
    int UseRDO_Q4 ;
#endif
#ifdef FastME
    int UseFME;
    int DynamicSearchRange;        //!< Dynamic Search Range
    int FMEScale;
    int NoET;
#endif

} input_t;

typedef struct image_par
{
    byte**  org_y_data;
    byte**  org_uv_data[2];
    int **y_residual;//[16][16]
    int **b8_residual;//[8][8]
    //int **b4_residual;
    int **b16_residual;//[16][16]  rong for ABT
    int **uv_residual[2];//[8][8]

    byte **mpr;

    int*  level;
    int*  run;
    int number;
    int ref_num;
    int curr_mb_nr;
    int total_mb_num;
    int curr_slice_nr;
    int type;
    int qp;
    int vbs_qp_16x16;    //  rong 0111  for ABT
    int vbs_qp_4x4;    //  rong 0111  for ABT
    int frame_rate;

    int width, height;
    int width_cr, height_cr;
    int p_width, p_height;
    int p_width_cr, p_height_cr;
    int mb_width, mb_height;
    int b8_width, b8_height;
    int mb_y, mb_x;
    int block8_y, block8_x;
    int pix_y, pix_x;
    int pix_c_y, pix_c_x;
    int cod_counter;
    int ****chromacofAC;
    int ****cofAC;
    int **cofAC16x16 ;
    int ***cofDC;

    int qadjust[3][16][16];  //Adaptive Rounding, N11, [YUV][16][16]
    int qadjust4x4[16][16];
    int blk_idx;            //N11

    macroblock_t *mb_data;
    syntax_element_t *mb_syntax_elements;
    int *quad;
    int tr;
#ifdef OPT_HP
	int tag_hp;//hierarchical p coding
	int hp_coding;
#endif
    int b_interval;
    int p_interval;
    int b_frame_to_code;
    int fw_mb_mode;
    int bw_mb_mode;
    mv_t pred_mv       [2][MAX_MODE_NUM][2][2];
    bi_mv_t bi_pred_mv    [MAX_MODE_NUM][2][2];
    mv_t mv            [2][MAX_MODE_NUM][2][2];
    bi_mv_t bi_mv         [MAX_MODE_NUM][2][2];
    mvd_t mvd          [2][MAX_MODE_NUM][2][2];
    bi_mvd_t bi_mvd       [MAX_MODE_NUM][2][2];
    mv_t mv_4x4            [2][4][4];//[ref_idx][b8][b4]
    bi_mv_t bi_mv_4x4      [4][4];
    mvd_t mvd_4x4          [2][4][4];
    bi_mvd_t bi_mvd_4x4    [4][4];

    int mv_range_flag;
    int auto_crop_right;
    int auto_crop_bottom;
    int buf_cycle;

    uint32_t frame_num;
    int coded_mb_nr;

    int curr_slice_start_mb;
    int curr_slice_qp;
    //int progressive_frame;
    //int picture_structure;
    int drop_flag;

    //int lum_var_flag;
    //int lum_scale[4];
    //int lum_shift[4];
    //int chroma_scale[4];
    //int chroma_shift[4];
    //int mb_weight_flag;
    //int weighting_prediction;
    int mpr_weight[16][16];
    int mb_no_currSliceLastMB;

    int number_of_header_bits;
    int number_of_texture_bits;
    int number_of_basic_unit_header_bits;
    int number_of_basic_unit_texture_bits;
    double total_mad_basic_unit;
    int mb_texture_bits;
    int mb_header_bits;
    int NumberofCodedBFrame;
    int NumberofCodedPFrame;
    int NumberofGOP;
    int TotalQpforPPicture;
    int NumberofPPicture;
    double mad_of_mb[10000];
    int BasicUnitQP;
    int IFLAG;
    int coded_mb;
    int basic_unit;
    int bot_MB;
    int seq_header_flag;
    int encode_end_flag;
    ushort_t bbv_delay;
    double lambda_mode, lambda_motion;
    int lambda_motion_factor;
    int skip_dir; //save the skip direction for B frame
} image_t;

typedef struct output_stream
{
    FILE *f;
    byte buf[STREAM_BUF_SIZE];
    uint32_t uPreBytes;
    int iBytePosition;
    int iBitOffset;
    int iNumOfStuffBits;
    int iBitsCount;
} output_stream_t;

//  rong 201001  for ABT
typedef enum
{
    NON_ABT,
    TRANS16,
    TRANS8,
    TRANS4,
    MAX_TRANS_NUM
} trans_t;

typedef struct stat_par
{
    float bitr;
    float bitrate;
    int bit_ctr;
    int bit_ctr_0;
    int bit_ctr_n;
    int bit_slice;
    int bit_use_mode_inter[2][MAX_MODE_NUM];
    int bit_ctr_emulationprevention;
    int mode_use_intra[25];
    int mode_use_inter[2][MAX_MODE_NUM];
    int bit_ctr_P;
    int bit_ctr_B;
    float bitrate_P;
    float bitrate_B;
    int bit_use_stuff_bits  [NUM_PIC_TYPE];
    int bit_use_mb_type     [NUM_PIC_TYPE];
    int bit_use_header      [NUM_PIC_TYPE];
    int bit_use_cbp         [NUM_PIC_TYPE];
    int bit_use_coeff_y     [NUM_PIC_TYPE];
    int bit_use_coeff_c     [NUM_PIC_TYPE];
    int bit_use_delta_quant [NUM_PIC_TYPE];
    int mode_use_inter_changed[2][MAX_STAT_MODE_NUM];
    int pred_direction_use[2][3][DIRECTION_NUM];   // [p/b][16/8/4][direction]
} stat_t;

typedef struct rd_data_par
{
    double min_rdcost;
    int rec_mbY[16][16];
    int rec_mbU[16][8];
    int ****cofAC;
    int ****chromacofAC;
    int ***cofDC;
    mvd_t mvd[2][2][2];
    int mb_type;
    int b8pdir[2][2];
    int frefar[2][2], brefar[2][2];
    int cbp;
    int mode;
    int *****pred_mv;
    int *****mv;
    int *****bi_mv;
} rd_data_t;

rd_data_t *rdopt;

qcoder_env_t* qcoder;
extern input_t *input;
extern image_t *img;

best_para_t     best_parameter;

int *allalpha_lum, *allbelta_lum;

int picture_distance;

FILE *p_log, *p_trace;
int p_rec, p_in;

int best_qadjust[3][2][2][16][16];  //Adaptive Rounding, N11, [YUV][16][16][ABT][levels]
int qoffset[3][3][2][16][16];  //Adaptive Rounding, N11, [YUV][IPB][Inter/Intra][yy][xx]
int qoffset4x4[3][2][16][16];  //Adaptive Rounding, N11, [IPB][Inter/Intra][yy][xx]

bitstream_t *tmp_stream;
int curr_slice_byte_pos;

bitstream_t *curr_stream, *rdo_stream;

mv_t    **frm_mv[MAX_REF_NUM_PLUS_1];
bi_mv_t **frm_bi_mv; //only used for B frame
mv_t    ****frm_mv_4x4[MAX_REF_NUM_PLUS_1];
bi_mv_t ****frm_bi_mv_4x4;

#ifdef FastME
mv_t    ****curr_frm_mv_4x4;
bi_mv_t ****curr_frm_bi_mv_4x4;
mv_t    ****last_frm_mv_4x4;
bi_mv_t ****last_frm_bi_mv_4x4;
int  is_lastI;
int  tr_lastP;
int  tr_lastB;
#endif

byte **p_img_y_rec;
byte **p_img_uv_rec[UV];
byte **img_y_rec_space[MAX_REF_NUM_PLUS_1];
byte **img_uv_rec_space[UV][MAX_REF_NUM_PLUS_1];
byte **img_y_rec_space_offset   [ MAX_REF_NUM_PLUS_1];
byte **img_uv_rec_space_offset[UV][ MAX_REF_NUM_PLUS_1];

byte **p_img_y_deblock;
byte **p_img_uv_deblock[UV];

byte   *imgY_org_buffer;

byte **img_y_org;
byte ***img_uv_org;

int min_v_mv, max_v_mv;
int min_h_mv, max_h_mv;

#if QUARTER_PIXEL
byte **y_up_sampling [ MAX_REF_NUM_PLUS_1] [ HALF_POS_NUM + QUATER_POS_NUM ];  //dw 20110808
#else
byte **y_up_sampling [ MAX_REF_NUM_PLUS_1] [ HALF_POS_NUM];
#endif



int intra_num[2];

int tot_b_frm_num;
int tot_time;
int tmp_buf_cycle;
int tot_metime;


char error_text[ET_SIZE];

int  intra_luma_residual_coding   ( int trans_index );
int  intra_chroma_residual_coding ( );
int inter_y_residual_coding   ( int trans_index );
int inter_uv_residual_coding ( );
int  write_mb_header();
int write_skip_flag();
int write_luma_intra_mode( int intramode, int block8x8, int block4x4 );
void find_skip_mv();
int get_skip_mode_cost();
void no_mem_exit( char *where );
int  get_mem_ACcoeff( int ***** );
int  get_mem_DCcoeff( int **** );
void free_mem_ACcoeff( int **** );
void free_mem_DCcoeff( int *** );
void encode_one_macroblock( int intra );
//int i_pic_header(int frame);
//int pb_pic_header();
void transform_b8( int** curr_blk );
#if TRACE
void trace2out( syntax_element_t * se );
#endif
typedef void ( *get_pred_mv_t )( mv_t *pred_mv, int ref_idx, int mb_pix_x, int mb_pix_y, int mode );
void error( char *text, int code );
int  start_sequence          ( );
int  terminate_sequence      ( );
void init_rdopt              ( );
void clear_rdopt             ( );
void init_me_module          ( );
void clear_me_module         ( );
void encode_one_frame        ( );
void pic_data                ( );
int  get_intra_mode_cost     ( );
void write_bs_to_file        ( );
int scanquant_b8( int qp, int intra_flag, int block8x8, int** curr_blk, int *cbp, int *cbp16x16 );
int scanquant_b8inb4 ( int qp, int mode,int block8x8, int **curr_blk, int scrFlag, int *cbp, int *cbp_blk, int ACLevel_4x4[4][17], int ACRun_4x4[4][17],int *bcbp );

int write_video_edit_code();


void get_residual      ( int mode, byte **org, byte **pred, int **residual );

void get_inter_pred_y( macroblock_t *currMB );
void get_inter_pred_uv( macroblock_t *currMB, int uv );
void init_bs( bitstream_t *target_stream );

int  write_block_coeff ( int block8x8 );
//void set_mode_and_ref ( int mode, macroblock_t *currMB);
void quant_b8( int qp, int intra_flag, int** curr_blk );

void decide_y_intra_b8_mode( int block8x8 );
void decide_y_intra_b4_mode( int block4x4 );

int  ( *me )    ( int ref_idx , int pic_pix_x , int pic_pix_y , int blocktype );
int  ( *me_bid )( int ref_idx , int pic_pix_x , int pic_pix_y , int blocktype );
int blk_me    ( int ref_idx , int pic_pix_x , int pic_pix_y , int blocktype );
int blk_me_bid( int ref_idx , int pic_pix_x , int pic_pix_y , int blocktype );

int qcoder_encode_inter_ref( qcoder_env_t* qcoder, int ref );
int qcoder_encode_intra_cbp( qcoder_env_t* qcoder, int cbp );
int qcoder_encode_inter_cbp( qcoder_env_t* qcoder, int cbp );
int qcoder_encode_delta_qp( qcoder_env_t* qcoder, int delta_qp );
int qcoder_encode_intra_luma_mode( qcoder_env_t* qcoder, int mode );
int qcoder_encode_intra_chroma_mode( qcoder_env_t* qcoder, int mode );
void qcoder_init( qcoder_env_t* qcoder, bitstream_t* currStream );
void qcoder_flush( qcoder_env_t* qcoder );
int qcoder_encode_eobflag( qcoder_env_t* qcoder, int eobflag );
int qcoder_encode_eobflag_8x8( qcoder_env_t* qcoder, int eobflag, int position );
int qcoder_encode_eobflag_4x4( qcoder_env_t* qcoder, int eobflag, int position );
int qcoder_encode_eobflag_chroma( qcoder_env_t* qcoder, int eobflag, int position );
int qcoder_encode_luma_8x8_coeff( qcoder_env_t* qcoder, int idx, int value, int intra );
int qcoder_encode_chroma_8x8_coeff( qcoder_env_t* qcoder, int idx, int value, int intra );
int qcoder_encode_luma_16x16_coeff( qcoder_env_t* qcoder, int idx, int value, int intra );
int qcoder_encode_luma_4x4_coeff( qcoder_env_t* qcoder, int idx, int value, int intra );
int qcoder_encode_transform_s16_flag( qcoder_env_t* qcoder, int s16flag );
int qcoder_encode_transform_s4_flag( qcoder_env_t* qcoder, int s4flag );
extern const int mode_blk_num[6]    ;
extern const int blk_offset_x[5][4] ;
extern const int blk_offset_y[5][4] ;

extern byte **intra_pred;
extern byte **inter_pred;

int **fw_refFrArr;
int **bw_refFrArr;


//added by wyp
pel_t  **nextP_imgY;
pel_t ***nextP_imgUV;
int glb_rdopt;
//for test
int trace_out;

//added by ckj inter4x4 will not be deblocked currently
#if DEBLOCK

pel_t  **p_img_y_rec_deblock;
pel_t ***p_img_uv_rec_deblock;
pel_t  **nextP_imgY_deblock;
pel_t ***nextP_imgUV_deblock;

void CopyAndDeblockFrame( image_t *img, byte **bufY, byte ***bufUV, byte **imgY, byte ***imgUV );
#endif

#endif
